﻿using System.Collections.Concurrent;
using AntQuartzUI.Services.Dtos;
using Quartz;
using Quartz.Impl.Matchers;

namespace AntQuartzUI.Services;

public class QuartzService : IQuartzService
{
    private readonly ISchedulerFactory _schedulerFactory;
    
    public QuartzService(ISchedulerFactory schedulerFactory)
    {
        _schedulerFactory = schedulerFactory;
    }
    
    /// <summary>
    /// 记录每个触发器（Trigger）被触发的次数
    /// </summary>
    public ConcurrentDictionary<TriggerKey, int> FireCountsDic { get; set; } = new();

    /// <summary>
    /// 记录每个触发器被“否决执行”（串行取消）的次数
    /// </summary>
    public ConcurrentDictionary<TriggerKey, int> VetoCountsDic { get; set; } = new();

    /// <summary>
    /// 获取所有作业
    /// </summary>
    /// <returns></returns>
    public async Task<List<JobStatusDto>> GetAllJobStatusesAsync()
    {
        var scheduler = await _schedulerFactory.GetScheduler();
        var jobGroups = await scheduler.GetJobGroupNames();

        var result = new List<JobStatusDto>();

        foreach (var group in jobGroups)
        {
            var jobKeys = await scheduler.GetJobKeys(GroupMatcher<JobKey>.GroupEquals(group));

            foreach (var jobKey in jobKeys)
            {
                var detail = await scheduler.GetJobDetail(jobKey);
                if (detail is null) continue;

                var jobInfo = new JobStatusDto
                {
                    JobName = detail.Key.Name,
                    GroupName = detail.Key.Group,
                    Description = detail.Description ?? string.Empty,
                    ExecuteModel = detail.ConcurrentExecutionDisallowed ? "串行" : "并发",
                    PersistJobDataAfterExecution = detail.PersistJobDataAfterExecution ? "是" : "否",
                    ClassName = detail.JobType.Name,
                    NameSpace = detail.JobType.Namespace ?? string.Empty,
                };

                var triggers = await scheduler.GetTriggersOfJob(jobKey);
                if (triggers.Count == 0) continue;

                foreach (var trigger in triggers)
                {
                    var triggerState = await scheduler.GetTriggerState(trigger.Key);
                    
                    var tiggerStatusDto = new TriggerStatusDto
                    {
                        TriggerName = trigger.CalendarName ?? trigger.Key.Name,
                        TriggerGroup = trigger.Key.Group,
                        FireCounts = FireCountsDic.GetValueOrDefault(trigger.Key, 0),
                        VetoCounts = VetoCountsDic.GetValueOrDefault(trigger.Key, 0),
                        ErrorCount = 0,
                        Priority = trigger.Priority,
                        TriggerType = "",
                        TimesTriggered = 0,
                        NextFireTime = trigger.GetNextFireTimeUtc() is null
                            ? string.Empty
                            : trigger.GetNextFireTimeUtc()!.Value.ToString("yyyy-MM-dd HH:mm:ss"),
                        PreviousFireTime = trigger.GetPreviousFireTimeUtc() is null
                            ? string.Empty
                            : trigger.GetPreviousFireTimeUtc()!.Value.ToString("yyyy-MM-dd HH:mm:ss"),
                        Status = triggerState switch
                        {
                            TriggerState.Normal => "正常",
                            TriggerState.Paused => "暂停",
                            TriggerState.Complete => "完成",
                            TriggerState.Error => "错误",
                            TriggerState.Blocked => "阻塞",
                            TriggerState.None => "不存在",
                            _ => throw new ArgumentOutOfRangeException(nameof(triggerState))
                        }
                    };

                    jobInfo.Triggers.Add(tiggerStatusDto);
                }

                result.Add(jobInfo);
            }
        }

        return result;
    }
    
    /// <summary>
    /// 暂停作业
    /// </summary>
    /// <param name="name"></param>
    /// <param name="group"></param>
    public async Task PauseTriggerAsync(string name, string group)
    {
        var scheduler = await _schedulerFactory.GetScheduler();
        var tiggerKey = new TriggerKey(name, group);
       
        await scheduler.PauseTrigger(tiggerKey);
    }

    /// <summary>
    /// 恢复作业
    /// </summary>
    /// <param name="name"></param>
    /// <param name="group"></param>
    public async Task StartTriggerAsync(string name, string group)
    {
        var scheduler = await _schedulerFactory.GetScheduler();
        var tiggerKey = new TriggerKey(name, group);
        await scheduler.ResumeTrigger(tiggerKey);
    }
    
}